#include "UILoader.hpp"
#include <stdexcept>
#include <fmt/format.h>

UILoader::UILoader()
{
  refBuilder=Gtk::Builder::create();
  try
  {
    refBuilder->add_from_file("Monitor.ui");
    cssProvider=Gtk::CssProvider::create();
    cssProvider->load_from_path("Monitor.css");
  }
  catch(...)
  {
    throw;
  }

  mainWindow=GetInstance<Gtk::Window>("mainWindow");
  mainWindow->set_hide_on_close();
  mainWindow->maximize();
  monitorGrid=GetInstance<Gtk::Grid>("monitorGrid");
  drawImage[1]=GetInstance<Gtk::DrawingArea>("drawCamera1");
  drawImage[1]->set_draw_func(std::bind(&UILoader::on_draw,
    this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,1));
  drawImage[2]=GetInstance<Gtk::DrawingArea>("drawCamera2");
  drawImage[2]->set_draw_func(std::bind(&UILoader::on_draw,
    this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,2));
  drawImage[3]=GetInstance<Gtk::DrawingArea>("drawCamera3");
  drawImage[3]->set_draw_func(std::bind(&UILoader::on_draw,
    this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,3));
  drawImage[4]=GetInstance<Gtk::DrawingArea>("drawCamera4");
  drawImage[4]->set_draw_func(std::bind(&UILoader::on_draw,
    this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,4));
  drawImage[5]=GetInstance<Gtk::DrawingArea>("drawCamera5");
  drawImage[5]->set_draw_func(std::bind(&UILoader::on_draw,
    this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,5));
  drawImage[0]=GetInstance<Gtk::DrawingArea>("drawResult");
  drawImage[0]->set_draw_func(std::bind(&UILoader::on_draw,
    this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,0));
  cameraList=GetInstance<Gtk::ColumnView>("listCameraStatus");
  imgLogo=GetInstance<Gtk::DrawingArea>("imgLogo");
  labTitle=GetInstance<Gtk::Label>("labTitle");

  labTmuxStatus=GetInstance<Gtk::Label>("labTmuxStatus");
  labTmuxStatus->set_text("设备未连接");
  labRecordStatus=GetInstance<Gtk::Label>("labRecordStatus");
  labRecordStatus->set_text("相机未开始采集");
  //代码无bug，谢谢
  m_listStore=Gio::ListStore<ModelColumns>::create();
  m_listStore->append(ModelColumns::create("相机1号","C1F48230AD","192.168.0.1"));
  m_listStore->append(ModelColumns::create("相机2号","C1REWEQACV","192.168.0.2"));
  m_listStore->append(ModelColumns::create("相机3号","C1DFAVDF34","192.168.0.3"));
  m_listStore->append(ModelColumns::create("相机4号","C1DADWEFVE","192.168.0.4"));
  m_listStore->append(ModelColumns::create("相机5号","C1DFADSVVV","192.168.0.5"));
  auto selection_model=Gtk::SingleSelection::create(m_listStore);
  selection_model->set_autoselect(true);
  cameraList->set_model(selection_model);
  cameraList->set_reorderable();

  auto factory=Gtk::SignalListItemFactory::create();
  factory->signal_setup().connect(sigc::mem_fun(*this,&UILoader::on_setup_label));
  factory->signal_bind().connect(sigc::bind(sigc::mem_fun(*this,&UILoader::on_bind_string),0));
  auto column=Gtk::ColumnViewColumn::create("相机名称",factory);
  cameraList->append_column(column);

  factory=Gtk::SignalListItemFactory::create();
  factory->signal_setup().connect(sigc::mem_fun(*this,&UILoader::on_setup_label));
  factory->signal_bind().connect(sigc::bind(sigc::mem_fun(*this,&UILoader::on_bind_string),1));
  column=Gtk::ColumnViewColumn::create("相机ID",factory);
  cameraList->append_column(column);

  factory=Gtk::SignalListItemFactory::create();
  factory->signal_setup().connect(sigc::mem_fun(*this,&UILoader::on_setup_label));
  factory->signal_bind().connect(sigc::bind(sigc::mem_fun(*this,&UILoader::on_bind_string),2));
  column=Gtk::ColumnViewColumn::create("相机IP",factory);
  cameraList->append_column(column);

  m_dispatcher.connect([this](){on_notification_from_work_thread();});
  imgLogo->set_draw_func(sigc::mem_fun(*this,&UILoader::on_imgLogo_draw));
}

UILoader::~UILoader()
{
  delete mainWindow;
}

template<class T>
T* UILoader::GetInstance(const char* name)
{
  T* ptr=refBuilder->get_widget<T>(name);
  if(ptr==nullptr)
    throw std::runtime_error(fmt::format("无法获取{}实例",name));
  ptr->set_name(name);
  ptr->get_style_context()->add_provider(cssProvider,1);
  return ptr;
}

void UILoader::ShowOriginImage(const ImageType& data,int index)
{
  if(index>5) return;
  std::lock_guard<std::mutex> lck(imageMutList[index]);
  imageList[index]=Gdk::Pixbuf::create_from_data
    (data.data,Gdk::Colorspace::RGB,false,8,data.width,data.height,data.width*3,
     [](const guint8* data){delete [] data;});
  imageUpdateFlag[index]=true;
  m_dispatcher.emit();
}

void UILoader::on_draw(const Cairo::RefPtr<Cairo::Context>& cr,int width,int height,int index)
{
  std::lock_guard<std::mutex> lck(imageMutList[index]);
  if(!imageList[index])
  {
    cr->set_source_rgb(1,1,1);
    cr->rectangle(0,0,width,height);
    cr->fill();
    cr->paint();
  }
  else
  {
    Gtk::DrawingArea* ptr=drawImage[index];
    Gdk::Cairo::set_source_pixbuf(cr, 
      imageList[index]->scale_simple(
        ptr->get_width(),
        ptr->get_width()*imageList[index]->get_height()/imageList[index]->get_width(),
        Gdk::InterpType::NEAREST),
      0, 
      0);
    cr->paint();
  }
}

void UILoader::on_notification_from_work_thread()
{
  for(int i=0;i<6;i++)
  {
    if(imageUpdateFlag[i])
    {
      imageUpdateFlag[i]=false;
      drawImage[i]->queue_draw();
    }
  }
  if(MobileStatus)
    labTmuxStatus->set_label("终端已连接");
  else
    labTmuxStatus->set_label("终端未连接");
  if(RecordStatus)
    labRecordStatus->set_label("正在录制");
  else
    labRecordStatus->set_label("没有录制");
}

void UILoader::on_setup_label(const Glib::RefPtr<Gtk::ListItem>& list_item)
{
  list_item->set_child(*Gtk::make_managed<Gtk::Label>(""));
}

void UILoader::on_bind_string(const Glib::RefPtr<Gtk::ListItem>& list_item,int index)
{
  auto col=std::dynamic_pointer_cast<ModelColumns>(list_item->get_item());
  if(!col)
    return;
  auto label=dynamic_cast<Gtk::Label*>(list_item->get_child());
  if(!label)
    return;
  switch(index)
  {
    case 0:
      label->set_text(col->m_col_name);
    break;
    case 1:
      label->set_text(col->m_col_id);
    break;
    case 2:
      label->set_text(col->m_col_ip);
    break;
  }
}

void UILoader::on_imgLogo_draw(const Cairo::RefPtr<Cairo::Context>& cr,int width,int height)
{
  auto image=Gdk::Pixbuf::create_from_file("Logo.png");
  Gdk::Cairo::set_source_pixbuf(cr,image->scale_simple(width,height,Gdk::InterpType::TILES));
  cr->paint();
}

void UILoader::SetMobileConnectStatus(bool status)
{
  MobileStatus=status;
}

void UILoader::SetRecordStatus(bool status)
{
  RecordStatus=status;
}
